home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / dev / c / AMesaRTL.lha / Mesa-2.6 / amiga / outputhandlers / grey / grey.c next >
C/C++ Source or Header  |  1998-09-19  |  8KB  |  425 lines

  1. //#define DB kprintf
  2. #define DB / ## /
  3.  
  4. //
  5. // OUTPUT HANDLER FOR AMIGAMESARTL
  6. // Szymon Ulatowski <szulat@friko6.onet.pl>
  7. //
  8. // supports "window" and "rportvport" output types
  9. //
  10.  
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <math.h>
  14.  
  15. #include <intuition/intuition.h>
  16. #include <proto/intuition.h>
  17. #include <proto/graphics.h>
  18. #include <proto/utility.h>
  19. #include <proto/exec.h>
  20. #include <proto/dos.h>
  21. #include <proto/layers.h>
  22. #include <dos/rdargs.h>
  23. #include <dos/dos.h>
  24.  
  25. #include <graphics/gfxbase.h>
  26.  
  27. #include "gl/outputhandler.h"
  28.  
  29. #define ARGSKEY "Dither/S"
  30.  
  31. long dither=0;
  32.  
  33. #define MAXPENS 256
  34.  
  35. #define MAXLOOKUP (7*256)
  36. #define RGBLOOKUP(r,g,b) (((r)<<1)+((g)<<2)+(b))
  37.  
  38. AmigaMesaRTLContext mesacontext;
  39. struct Window *window;
  40. ULONG mode;
  41. struct BitMap *tmpbm;
  42. struct RastPort tmprp;
  43. UBYTE pens[MAXPENS];
  44. UBYTE *qbuffer;
  45. short havepens;
  46. ULONG numc;
  47. UBYTE lookup[MAXLOOKUP];
  48. short realtab[MAXPENS];
  49. int bufwidth,bufheight;
  50. int fullwindow;
  51. int newpalette;
  52.  
  53. struct RPortVPort
  54. {
  55. struct RastPort *RPort;
  56. struct ViewPort *VPort;
  57. long LeftEdge,TopEdge;
  58. long Width,Height;
  59. };
  60.  
  61. struct Library *mesadriverBase;
  62. struct RPortVPort rpvp;
  63.  
  64. #define WINWIDTH(w)        ((w)->Width - (w)->BorderLeft - (w)->BorderRight)
  65. #define WINHEIGHT(w)    ((w)->Height - (w)->BorderTop - (w)->BorderBottom)
  66.  
  67. void ReadPrefs(char *prefs)
  68. {
  69. char *pr=malloc(strlen(prefs)+2);
  70. struct RDArgs *my_rda=0,*rda=0;
  71. strcpy(pr,prefs);
  72. strcat(pr,"\n");
  73. DB("got prefs '%s'\n",prefs);
  74. if (my_rda=AllocDosObject(DOS_RDARGS,0))
  75.     {
  76.     my_rda->RDA_Source.CS_Buffer=pr;
  77.     my_rda->RDA_Source.CS_Length=strlen(pr);
  78.     rda=ReadArgs(ARGSKEY,&dither,my_rda);
  79.     if (rda) FreeArgs(rda);
  80.     else dither=0;
  81.     FreeDosObject(DOS_RDARGS,my_rda);
  82.     }
  83. free(pr);
  84. }
  85.  
  86. BOOL InitWritePixelA8(void)
  87. {
  88. if (!rpvp.RPort) return 0;
  89.     if (!(tmpbm=AllocBitMap(bufwidth,1,rpvp.RPort->BitMap->Depth,0,0)))
  90.         return 0;
  91.  
  92.     tmprp = *(rpvp.RPort);
  93.     tmprp.Layer = 0;
  94.     tmprp.BitMap = tmpbm;
  95.  
  96.     return 1;
  97. }
  98.  
  99. void DelWritePixelA8(void)
  100. {
  101. if (tmpbm) FreeBitMap(tmpbm);
  102. tmpbm=0;
  103. }
  104.  
  105. int findbest(int v)
  106. {
  107. int i;
  108. int bestv=MAXLOOKUP,besti,d;
  109. for (i=0;i<numc;i++)
  110.     {
  111.     d=abs(realtab[pens[i]]-v);
  112.     if (d<bestv) {bestv=d; besti=i;}
  113.     }
  114. return pens[besti];
  115. }
  116.  
  117. void AllocPens(int makelookup)
  118. {
  119. unsigned char got[MAXPENS];
  120. unsigned long rgb[3];
  121. int i,step,val,ready;
  122.  
  123. if ((!havepens)&&(rpvp.VPort))
  124.     {
  125.     numc=min(256,rpvp.VPort->ColorMap->Count);
  126.     step=256; ready=0;
  127.     memset(got,0,MAXPENS);
  128.     for (;;)
  129.         {
  130.         for (val=0;val<=256;val+=step)
  131.             {
  132.             if (val==256) val=255;
  133.             if (got[val]) continue;
  134.             pens[ready]=ObtainBestPen(rpvp.VPort->ColorMap,
  135.                 val*0x01010101,val*0x01010101,val*0x01010101,0);
  136.             got[val]=1;
  137.             ready++;
  138.             if (ready>=numc) goto finished;
  139.             }
  140.         step/=2;
  141.         }
  142.     finished:
  143.  
  144.     for (i=0;i<numc;i++)
  145.         {
  146. //        GetRGB32(rpvp.VPort->ColorMap,pens[i],1,rgb);
  147.         GetRGB32(rpvp.VPort->ColorMap,i,1,rgb);
  148.         realtab[i]=RGBLOOKUP(rgb[0]>>24,rgb[1]>>24,rgb[2]>>24);
  149.         }
  150.     makelookup=1;
  151.     }
  152.  
  153. if (makelookup)
  154. {
  155. if (mode==AMRTL_RGBAMode)
  156. //for (i=0;i<MAXLOOKUP;i++)    lookup[i]=pens[findbest(i)];
  157. for (i=0;i<MAXLOOKUP;i++)    lookup[i]=findbest(i);
  158. else
  159.     {
  160.     ULONG *pal;
  161.     AmigaMesaRTLGetContextAttr(AMRTL_IndexPalette,mesacontext,&pal);
  162.     for (i=0;i<MAXPENS;i++,pal+=3)
  163.         lookup[i]=findbest(RGBLOOKUP(pal[0]>>24,pal[1]>>24,pal[2]>>24));
  164. //        lookup[i]=pens[findbest(RGBLOOKUP(pal[0]>>24,pal[1]>>24,pal[2]>>24))];
  165.     }
  166. }
  167. havepens=1;
  168. }
  169.  
  170. void FreePens(void)
  171. {
  172. int i;
  173. if ((havepens)&&(rpvp.VPort))
  174.     {
  175.     for (i=0;i<numc;i++)
  176.         ReleasePen(rpvp.VPort->ColorMap,pens[i]);
  177.     }
  178. havepens=0;
  179. }
  180.  
  181. void ChangeEnvironment(struct RPortVPort *chg)
  182. {
  183. if ((!chg)||(!(chg->VPort))) FreePens();
  184.  
  185. if ((!chg)||(!(chg->RPort))) DelWritePixelA8();
  186.  
  187. if (chg) rpvp=*chg; else memset(&rpvp,0,sizeof(rpvp));
  188. }
  189.  
  190. __asm __saveds int InitOutputHandlerA(register __a0 AmigaMesaRTLContext ctx, register __a1 struct TagItem *tags)
  191. {
  192.     char *outputtype;
  193.     void *output;
  194.     char prefs[1000]={0};
  195.  
  196.     if (GfxBase->LibNode.lib_Version<39) return 0;
  197.  
  198.     mesadriverBase = (struct Library *)GetTagData(OH_DriverBase,NULL,tags);
  199.     if(!mesadriverBase)
  200.         return 0;
  201.  
  202.     AmigaMesaRTLGetContextAttr(AMRTL_Mode,ctx,&mode);
  203.  
  204.     GetVar("AmigaMesaRTL/grey.prefs",prefs,1000,0);
  205.     ReadPrefs(GetTagData(OH_Parameters,prefs,tags));
  206.  
  207.     qbuffer = NULL;
  208.     havepens=0;
  209.  
  210.     tmpbm=0;
  211.  
  212.     numc = 2;
  213.  
  214.     newpalette=0;
  215.     rpvp.RPort=0;
  216.     rpvp.VPort=0;
  217.     rpvp.LeftEdge=rpvp.TopEdge=0;
  218.     rpvp.Width=16; rpvp.Height=16;
  219.  
  220.     mesacontext = ctx;
  221.     outputtype = (char *)GetTagData(OH_OutputType,NULL,tags);
  222.     output = (void*)GetTagData(OH_Output,NULL,tags);
  223.     if (outputtype)
  224.         {
  225.         if (output&&(!stricmp(outputtype,"window")))
  226.             {
  227.             window=(struct Window*)output;
  228.             rpvp.TopEdge=window->BorderTop;
  229.             rpvp.LeftEdge=window->BorderLeft;
  230.             rpvp.RPort=window->RPort;
  231.             rpvp.VPort=ViewPortAddress(window);
  232.             numc=min(256,rpvp.VPort->ColorMap->Count);
  233.             fullwindow=1;
  234.             }
  235.         else if (!stricmp(outputtype,"rportvport"))
  236.             {
  237.             fullwindow=0;
  238.             ChangeEnvironment(output);
  239.             }
  240.         else return 0;
  241.         }
  242.     else return 0;
  243.  
  244.     return 1;
  245. }
  246.  
  247. __asm __saveds void DeleteOutputHandler(void)
  248. {
  249.     FreePens();
  250.  
  251.     DelWritePixelA8();
  252.  
  253.     if(qbuffer) free(qbuffer);
  254.     qbuffer = NULL;
  255.  
  256. mesadriverBase=0;
  257. }
  258.  
  259. __asm __saveds int ResizeOutputHandler(void)
  260. {
  261. // if (!rpvp.RPort) return;
  262.     DelWritePixelA8();
  263.     if(qbuffer) free(qbuffer);
  264.     qbuffer = NULL;
  265.  
  266. AmigaMesaRTLGetContextAttr(AMRTL_BufferWidth,
  267.     mesacontext,&bufwidth);
  268. AmigaMesaRTLGetContextAttr(AMRTL_BufferHeight,
  269.     mesacontext,&bufheight);
  270.  
  271. AmigaMesaRTLGetContextAttr(AMRTL_OutputWidth,
  272.     mesacontext,&rpvp.Width);
  273. AmigaMesaRTLGetContextAttr(AMRTL_OutputHeight,
  274.     mesacontext,&rpvp.Height);
  275.  
  276.     qbuffer = (UBYTE *)calloc(bufwidth * bufheight, sizeof(UBYTE));
  277.  
  278.     InitWritePixelA8();
  279.  
  280.     return 1;
  281. }
  282.  
  283. __asm __saveds int ProcessOutput(void)
  284. {
  285. UBYTE *buffer,*in;
  286. int i;
  287. unsigned char *q;
  288.  
  289. AmigaMesaRTLGetContextAttr(AMRTL_Buffer,mesacontext,&buffer);
  290.  
  291. if ((!bufwidth)||(!bufheight)) {DisplayBeep(0); return 1;}
  292. if (!qbuffer) return 1;
  293.  
  294. if (rpvp.VPort)
  295.     {
  296.     if ((!havepens)||(newpalette)) AllocPens(newpalette);
  297.  
  298.     if(mode == AMRTL_RGBAMode)
  299.         {
  300. if (dither)
  301.         {
  302.         short error=0,b;
  303.         for (q=qbuffer,in=buffer,i=bufwidth*bufheight;i>0;i--,q++,in+=4)
  304.             {
  305.             b=(short)RGBLOOKUP(in[0],in[1],in[2])+error;
  306.             *q=lookup[max(0,min((MAXLOOKUP-1),b))];
  307.             error=(b-realtab[*q])/2;
  308.             }
  309.         }
  310. else
  311.         for (q=qbuffer,in=buffer,i=bufwidth*bufheight;i>0;i--,q++,in+=4)
  312.             *q=lookup[RGBLOOKUP(in[0],in[1],in[2])];
  313.         }
  314.     else
  315.         {
  316.         for (q=qbuffer,in=buffer,i=bufwidth*bufheight;i>0;i--,q++,in++)
  317.             *q=lookup[*in];
  318.         }
  319.     }
  320. if (rpvp.RPort)
  321.     {
  322.     struct Region *re=0,*oldre;
  323.     if (!tmpbm) InitWritePixelA8();
  324.  
  325.     if (fullwindow)
  326.         {
  327.         if ((rpvp.Width>WINWIDTH(window))||(rpvp.Height>WINHEIGHT(window)))
  328.             {
  329.             struct Rectangle rect;
  330. DB("wpa8 needs clipping!\n");
  331.             rect.MinX=window->BorderLeft;
  332.             rect.MinY=window->BorderTop;
  333.             rect.MaxX=window->BorderLeft+WINWIDTH(window)-1;
  334.             rect.MaxX=window->BorderTop+WINHEIGHT(window)-1;
  335.             re=NewRegion();
  336.             OrRectRegion(re,&rect);
  337.             oldre=InstallClipRegion(rpvp.RPort->Layer,re);
  338.             }
  339.         }
  340.  
  341.     WritePixelArray8(rpvp.RPort,
  342.      rpvp.LeftEdge , rpvp.TopEdge,
  343.      rpvp.LeftEdge + rpvp.Width-1, rpvp.TopEdge + rpvp.Height-1,
  344.      qbuffer, &(tmprp));
  345.  
  346.     if (re)
  347.         {
  348.         InstallClipRegion(rpvp.RPort->Layer,oldre);
  349.         DisposeRegion(re);
  350.         }
  351.     }
  352.     return 1;
  353. }
  354.  
  355.  
  356. __asm __saveds void SetIndexRGBTable(register __d0 int index, register __a0 ULONG *rgbtable, register __d1 int numcolours)
  357. {
  358. newpalette=1;
  359. }
  360.  
  361. __asm __saveds ULONG SetOutputHandlerAttrsA(register __a0 struct TagItem *tags)
  362. {
  363. struct TagItem *tstate, *tag;
  364. ULONG tidata;
  365.  
  366. tstate = tags;
  367. while(tag = NextTagItem(&tstate))
  368. {
  369.     tidata = tag->ti_Data;
  370.     switch(tag->ti_Tag)
  371.     {
  372.         case OH_Output:
  373.             if (!fullwindow) ChangeEnvironment((struct RPortVPort*)tidata);
  374.             break;
  375. /*        case OH_NumColours:
  376.             SetColourRange(reqfirstc,tidata);
  377.             break;
  378. */        default:
  379.             break;
  380.     }
  381. }
  382. return(0);
  383. }
  384.  
  385.  
  386. __asm __saveds ULONG GetOutputHandlerAttr(register __d0 ULONG attr, register __a0 ULONG *data)
  387. {
  388.     switch(attr)
  389.     {
  390.         case OH_Output:
  391.             *((struct Window **)data) = window;
  392.             break;
  393.         case OH_OutputType:
  394.             *((char **)data) = "Window";
  395.             break;
  396.         case OH_Width:
  397.             if (fullwindow) *data=WINWIDTH(window);
  398.             else    *data = rpvp.Width;
  399.             break;
  400.         case OH_Height:
  401.             if (fullwindow) *data=WINHEIGHT(window);
  402.             else    *data = rpvp.Height;
  403.             break;
  404.         case OH_NumColours:
  405.